Skip to content

Conversation

@alexandre-daubois
Copy link
Member

Use zend_update_property() instead of doing things "manually".

@alexandre-daubois alexandre-daubois linked an issue Nov 3, 2025 that may be closed by this pull request
@alexandre-daubois alexandre-daubois marked this pull request as ready for review November 3, 2025 09:02
Copy link
Member

@ndossche ndossche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a phone , so can't check. But you're looking at the property info now, however dynamic properties don't have any. So that means that a dynamically created property $stream would've been overwritten before this patch but now no longer. So that is an unintended behaviour change.

@alexandre-daubois
Copy link
Member Author

Oh alright, I wasn't aware of this subtlety of dynamic properties. Let's refine that.

@bukka
Copy link
Member

bukka commented Nov 3, 2025

Hmm so that would require to someone create the dynamic property in filter first and it could then be used in subsequent calls for stream, right? If so, that sounds like a proper edge case... :)

@ndossche
Copy link
Member

ndossche commented Nov 3, 2025

The easiest way to test this is to create a onCreate method that sets a dynamic property on $this

@ndossche
Copy link
Member

ndossche commented Nov 4, 2025

This will work, except for a pre-existing bug:
When there is an unset or uninit typed property, but it is declared, its existence will be ignored.

It would also be great to try to avoid OBJPROP so that the property table isn't rebuilt, but that isn't critical.

@alexandre-daubois
Copy link
Member Author

alexandre-daubois commented Nov 4, 2025

I tried to implement what you have in mind in 04e0955

@alexandre-daubois alexandre-daubois force-pushed the user-stream-filter-props branch 2 times, most recently from 7208c60 to 04e0955 Compare November 4, 2025 08:33
Copy link
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me!

Maybe @bukka or @ndossche want to take another look.

Copy link
Member

@ndossche ndossche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this. As I said in the issue I opened, it's a bit of an annoying issue (as you have felt).

if (Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL)) {
zval null_zval;
ZVAL_NULL(&null_zval);
zend_update_property_ex(Z_OBJCE_P(obj), Z_OBJ_P(obj), stream_name, &null_zval);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use zend_update_property_null.


zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0);
if (Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL)) {
zval stream_zval;
Copy link
Member

@ndossche ndossche Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good follow-up for master would be to clean up the duplication of the error branches.
(You don't need to do anything with this comment in this PR, this is just a note for future work)

#include "ext/standard/basic_functions.h"
#include "ext/standard/file.h"
#include "ext/standard/user_filters_arginfo.h"
#include "zend_exceptions.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you need this include?

EG(fake_scope) = Z_OBJCE_P(obj);

zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0);
if (Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to use a cache slot anyway as you repeat the check below, not critical though.
Alternatively: The previous code remembered whether the property existed, perhaps you can do this too, but it's not critical. This alternative idea seems clean as it would simplify the code a bit further.

php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade");
}
zend_string_release(stream_name);
EG(fake_scope) = old_scope;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to restore the fake scope prior to emitting the warning such that potential error handlers can't utilise the fake scope (not sure).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User filters allow breaking typed properties

5 participants